#requires -version 2.0 
function Get-NaVol {
	<#
	.Synopsis
   		Get volume status.
	.Description
   		Get volume status. Note that all RAID-related status items (e.g., 'RaidSize', 'RaidStatus', 'ChecksumStyle')
 		reported for a flexible volume actually describe the state of its containing aggregate. 
	.Parameter volume
   		The name of the volume for which we want status information. 
 		if not supplied, then we want status for all volumes on the filer.  
	.Parameter Server
   		NaServer to query
	.Example
   		PS > Get-NaVol
	.Outputs
    	NetApp.SDK.NaVol[]
    .Link
    	Set-NaVol
    	Remove-NaVol
    	Rename-NaVol
    	New-NaVol
	#>
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,HelpMessage="The name of the volume for which we want status information.")]
		[Alias("Volume")]
		[STRING]
		$name,
			
		[Parameter(Position=1,HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-list-info")
		$request.AddNewChild("verbose",$TRUE)
		if ($Name){
			$request.AddNewChild("volume",$Name)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result.volumes."volume-info" | % {
				$p = new-object Collections.Hashtable
				$_.plexes."plex-Info" | % { 
					$rg = new-object Collections.Hashtable
					$_."raid-groups"."raid-group-info" |% {
						if ($_."reconstruction-percentage" -eq $null){
							$reconstruction = 0
						}
						else{
							$reconstruction = $_."reconstruction-percentage"
						}
					
						$RaidGroup = New-Object NetApp.SDK.NaRaidGroup -ArgumentList @(
								"/vol$($_.Name)", 
								(ConvertFrom-NaBool $_.Reconstructing),
								[array]($_.disks."disk-info"|%{$_.name}),
								$reconstruction
							)
						$rg.add(($_.Name.split('/')[3]), $RaidGroup)
					}
					if ($_."resyncing-percentage" -eq $null)
					{
						$resyncing = 0
					}
					else
					{
						$resyncing = $_."resyncing-percentage"
					}
					$plx = New-Object NetApp.SDK.NaPlex -ArgumentList @(
							"/vol$($_.name)", 
							(ConvertFrom-NaBool $_."is-online"), 
							(ConvertFrom-NaBool $_."is-resyncing"),
							$RG,
							$resyncing
						)
					$p.add(($_.name.split('/')[2]), $plx)
				}
				$Compression = New-Object NetApp.SDK.NaVolumeCompression -ArgumentList @(
							$_.Compression."Compression-info"."compressed-data",
							$_.Compression."Compression-info"."data-decompressed",
							$_.Compression."Compression-info"."decomp-compelete-percentage",
							(ConvertFrom-NaBool $_.Compression."Compression-info"."is-compression-enabled"),
							$_.Compression."Compression-info"."saved-percentage"
						)
				$SIS = New-Object NetApp.SDK.NaSISinfo -ArgumentList @(
								$_.sis."sis-info"."last-operation-begin",
								$_.sis."sis-info"."last-operation-end",
								$_.sis."sis-info"."last-operation-error",
								$_.sis."sis-info"."last-operation-size",
								$_.sis."sis-info"."percentage-saved",
								$_.sis."sis-info"."progress",
								$_.sis."sis-info"."schedule",
								$_.sis."sis-info"."size-saved",
								$_.sis."sis-info"."size-shared",
								$_.sis."sis-info"."state",
								$_.sis."sis-info"."status",
								$_.sis."sis-info"."type"
							)
				return New-Object NetApp.SDK.NaVolume -ArgumentList @(
					$_."checksum-style",
					[Array]($_."clone-children"."clone-child-info"| % {$_."clone-child-name"}),
					$_."clone-parent"."clone-parent-info"."parent-volume-name",
					$_."clone-parent"."clone-parent-info"."parent-snapshot-name",
					$Compression,
					$_."containing-aggregate",
					$_."disk-count",
					$_."files-total",
					$_."files-used",
					$_."formatted-expiry-date",
					(ConvertFrom-NaBool $_."is-checksum-enabled"),
					(ConvertFrom-NaBool $_."is-inconsistent"),
					(ConvertFrom-NaBool $_."is-invalid"),
					(ConvertFrom-NaBool $_."is-snaplock"),
					(ConvertFrom-NaBool $_."is-unrecoverable"),
					$_."mirror-status",
					$_."name",
					$_."owning-vfiler",
					"/vol/$($_.name)",
					$_."percentage-used",
					$_."plex-count",
					$P,
					$_."quota-init",
					$_."raid-size",
					$_."raid-status",
					$_."remote-location",
					$_."reserve",
					$_."reserve-required",
					$_."reserve-used",
					$_."reserve-used-actual",
					$SIS,
					$_."size-available",
					$_."size-total",
					$_."size-used",
					$_."snaplock-type",
					$_."snapshot-blocks-reserved",
					$_."snapshot-percent-reserved",
					$_."space-reserve",
					(ConvertFrom-NaBool $_."space-reserve-enabled"),
					$_."state",
					$_."type",
					$_."uuid"
				)
			}
		}
	}
}
function New-NaVol {
	<#
	.Synopsis
    	Create a new volume
	.Description
   		Create a new flexible, Cache, or sparse volume with the given name and characteristics. Up to 200 
 		volumes can be created on each filer. Use the New-Aggr cmdlet with the -traditional switch to 
 		create a traditional volume.
	.Parameter Name
   		Name of the volume to create. The volume name can contain letters, numbers, and the underscore character (_),
 		but the first character must be a letter or an underscore. 
	.Parameter Aggregate
   		The name of the aggregate in which to create the new flexible volume. If provided, this argument must be 
		accompanied by the "size" parameter described below. 
	.Parameter Size
   		The initial size of the new flexiblgete volume in KB.
	.Parameter Reserve
	  	Specifies the type of volume guarantee the new volume will use. Possible values: none, file, volume. If this
   		argument is not provided, the default volume guarantee type is volume. 
	.Parameter LanguageCode
   		Specifies the language to use for the new volume via a language code. 
 		The default language is the one used by the filer's root volume.

 		Available language codes are: 	
 		C (POSIX) 
 		da (Danish)
 		de (German)
 		en (English)
 		en_US (English (US)) 
		es (Spanish)
 		fi (Finnish)
 		fr (French)
 		he (Hebrew)
 		it (Italian)
 		ja (Japanese euc-j) 
 		ja_JP.PCK (Japanese PCK (sjis))
 		ko (Korean)
 		no (Norwegian)
 		nl (Dutch)
 		pt (Portuguese)
		sv (Swedish)
 		zh (Simplified Chinese)
		zh.GBK (Simplified Chinese (GBK))
 		zh_TW (Traditional Chinese euc-tw) 
 		zh_TW.BIG5 (Traditional Chinese Big 5)
 
 		NOTE: 	To use UTF-8 as the NFS character set, append '.UTF-8'. 
	.Parameter FlexCacheSource
   		Specifies the remote host and volume name for the origin of the FlexCache. A FlexCache license is necessary
		for this option to be utilized. The default action is not to create a FlexCache Volume. 
 		Format: <remote host>:<remote volume> 
   		Create a sparse volume as a FlexCache for the given remote host and remote volume name. 
 
 		Remote Host: Should be formatted as either the DNS hostname or as an IP address. 
		Remote Volume: Should be formatted the same as a volume name. 
	
 		Note: 	ESERVICENOTLICENSED is returned if the FlexCache service is not licensed. 
 				EINVALIDINPUT is returned if the host, or source volume is found to be invalid. 
	.Parameter SnapLockType
   		Specifies the type of Snaplock volume to be created. Possible values - "compliance" or "enterprise" 
 	
 		NOTE: 	ESERVICENOTLICENSED is returned if the necessary Snaplock compliance or enterprise license has not been installed.
 				EINVALIDINPUT is returned if -SnapLockType has an illegal value.
 				EONTAPI_EWORMNOCLOCK is returned if SnapLock Compliance Clock is not running. 
	.Parameter Server
	    NaServer to query
	.Example
	    # Create a 21mb volume named vol1 in aggr1 
	    Get-NaAggr aggr1 | New-NaVol -Name vol1 -size 21mb
	.Example
	    # Create a new flexcache volume named vol1_cache using vol1 on TOASTER as the flexcache source.
    	New-NaVol -Name vol1_cache -Aggregate aggr0 -size 20mb -FlexCacheSource TOASTER:vol1
	.Example
	    #  Create a new Snaplock compliance volume named vol3 on the snaplock compliant aggr aggr3
	    New-NaVol vol3 -aggregate aggr3 -size 22mb -snaplocktype compliance
	.Outputs
    	NetApp.SDK.NaVol[]
    .Link
    	Get-NaVol
    	Set-NaVol
    	Remove-NaVol
    	Rename-NaVol
	#>
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Position=0,Mandatory=$TRUE,HelpMessage="Name of the volume to create.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Mandatory=$TRUE,HelpMessage="The name of the aggregate in which to create the new flexible volume.")]
		[Alias("ContainingAggregate")]
		[string]
		$Aggregate,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,Position=1,Mandatory=$TRUE,HelpMessage="The initial size in kb of the new flexible volume.")]
		[Alias("SizeTotal")]
		[Int64]
		$size,
	
		[Parameter(HelpMessage="Specifies the type of volume guarantee the new volume will use.")]
		[ValidateSet("none","file","volume")]
		[string]
		$Reserve,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Specifies the language to use for the new volume via a language code.")]
		[ValidateSet("C","da","de","en","en_US","es","fi","fr","he","it","ja","ja_JP.PCK","ko","no","nl","pt","sv","zh","zh.GBK","zh_TW","zh_TW.BIG5")]
		[STRING]
		$LanguageCode,
	
		[Parameter(HelpMessage="Specifies the remote host and volume name for the origin of the FlexCache.")]
		[string]
		$FlexCacheSource,
	
		[Parameter(HelpMessage="Specifies the type of Snaplock volume to be created.")]
		[ValidateSet("compliance","enterprise")]
		[STRING]
		$SnaplockType,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-create")
		$request.AddNewChild("volume",$Name)
		$request.AddNewChild("containing-aggr-name",$Aggregate)
		$request.AddNewChild("size",$size)
		if ($LanguageCode){
			$request.AddNewChild("language-code",$LanguageCode)
		}
		if ($FlexCacheSource){
			$request.AddNewChild("remote-location",$FlexCacheSource)
		}
		if ($SnaplockType){
			$request.AddNewChild("snaplock-type",$SnaplockType)
		}
		if ($Reserve){
			$request.AddNewChild("space-reserve",$Reserve)
		}
		if ($pscmdlet.ShouldProcess($Aggregate,"Creating volume $Name ")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaVol $Name -server $server
			}
		}
	}
}
function Rename-NaVol {
	<#
	.Synopsis
    	Renames the specified volume to a new name specified by -NewName.
	.Description
   		Renames the specified volume to a new name specified by -NewName. If the volume is referenced in the /etc/exports file, 
 		remember to make the name change in /etc/exports also so that the affected file system can be exported by the filer after
 		the filer reboots. The rename-navol cmdlet does not automatically update the /etc/exports file.
	.Parameter Name
   		Name of the volume to rename.
	.Parameter NewName
   		The new name desired for the volume.
	.Parameter Server
	    NaServer to query
	.Example
		# rename vol1 to vol2
   		PS > Get-NaVol vol1 | Rename-NaVol -NewName vol2
   	.Outputs
    	NetApp.SDK.NaVol[]
    .Link
    	Get-NaVol
    	Set-NaVol
    	Remove-NaVol
    	New-NaVol
	#>
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]	
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume to rename.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(Position=1,Mandatory=$TRUE,HelpMessage="The new name desired for the volume.")]
		[string]
		$NewName, 
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-rename")
		$request.AddNewChild("volume",$Name)
		$request.AddNewChild("new-volume-name",$NewName)
		if ($pscmdlet.ShouldProcess($Server.Server,"Renaming $Name to $newname")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
				Get-naVol -Name $NewName -Server $server
			}
		}
	}
}
function Remove-NaVol {
	<#
	.Synopsis
    	Destroy the specified volume or plex.
	.Description
   		Destroy the specified volume or plex. If a flexible volume is specified, all of its blocks are freed and returned to its
 		containing aggregate; no other flexible volumes in the same containing aggregate (if any) are affected. if a traditional
 		volume is specified, all of its plexes are destroyed, and its disks are returned to the appropriate spare pool(s). if a
 		plex is specified, it must be for a mirrored aggregate (which could potentially be embedded in a traditional volume), 
		leaving it unmirrored. Only offline volumes and plexes can be destroyed.
	.Parameter Name
 		Name of an existing volume or plex. 
	.Parameter force
   		Force the destruction of the volume even if a non-default vfiler has storage on it. Normally, the system will not destroy
 		such a volume and will instead return EVOLUME_HAS_VFILER_STORAGE.
	.Parameter Server
	    NaServer to query
	.Example
		# remove vol1
   		PS > Get-naVol vol1 | set-NaVol -offline | remove-navol
    .Link
    	Get-NaVol
    	Set-NaVol
    	Rename-NaVol
	#>
	[CmdletBinding(
		SupportsShouldProcess=$TRUE,
	    SupportsTransactions=$False, 
	    ConfirmImpact="High",
	    DefaultParameterSetName=""
	)]	
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of an existing volume or plex.")]
		[Alias("Volume")]
		[STRING]
		$Name,
		
		[Parameter()]
		[switch]
		$force,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-destroy")
		$request.AddNewChild("name",$Name)
		if ($force){
			$request.AddNewChild("force",$TRUE)
		}
		if ($pscmdlet.ShouldProcess($Server.Server,"Destroy volume $($Name)")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
Function Set-NaVol {
	<#
	.Synopsis
    	Used to Set the State of a volume/plex.
	.Description
	    Used to Set the State of a volume/plex.
	.Parameter Name
   		Name of the volume.
	.Parameter Offline
   		Take the specified volume or plex offline, making it unavailable for both user-level data access and RAID-level access 
 		(unless it's a flexible volume, at which time its containing aggregate is not affected in any way, and will remain fully
 		online). The operation takes effect before the API returns except in maintenance mode, when the current root volume may
 		not be taken offline. A volume marked to become the root cannot be taken offline. Taking a flexible volume offline does
 		not affect its containing aggregate in any way. A number of operations being performed on the given volume (or its 
 		containing aggregate) can prevent this operation from succeeding, either at all or for various lengths of time. if such
 		operations are found, the system waits up to one second for them to finish. if they don't, the command is aborted. A check
 		is also made for files on the volume opened by internal ONTAP processes. The command is aborted if any are found.
	.Parameter Online
   		Bring the specified volume or the plex online. This command takes effect immediately. If there are CIFS shares associated
 		with the volume, they are enabled.
	.Parameter Restrict
   		Restrict the specified volume, making it unavailable for user-level data access but leaving it (or its containing aggregate,
 		if it's a flexible volume) available to internal OnTAP RAID-level access.
	.Parameter CifsDelay
   		If a volume contains CIFS shares, users should be warned before taking the volume offline/restricted. This argument specifies
 		the number of minutes to delay before taking the volume offline, during which time CIFS users are warned of the pending loss
 		of service. A -CifsDelay time of 0 means that the volume is to be taken offline immediately without issuing any warnings. CIFS
		users can lose data if they are not given a chance to terminate applications gracefully. By default, the value of -CifsDelay is 0.
	.Parameter Server
	    NaServer to query
	.Example
	    # Offline vol1 
   		PS > Set-NaVol -Volume vol1 -offline
	.Example
    	# restrict vol2 
    	PS > Set-Navol -volume vol1 -Restrict 
	.Example
    	# Online restricted/offlined aggregates 
    	PS > Get-NaVol | ? {$_.Status -ne "online"} | Set-NaVol -Online
    .Outputs
    	NetApp.SDK.NaVol[]
    .Link
    	Get-NaVol
    	New-NaVol
    	Remove-NaVol
    	Rename-NaVol
	#>
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="online")]
	param(
		[Parameter(ParameterSetName="online",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the existing volume or plex.")]
        [Parameter(ParameterSetName="restrict",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the existing volume or plex.")]
        [Parameter(ParameterSetName="offline",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Path of the existing volume or plex.")]
        [Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(ParameterSetName="offline")]
		[switch]
		$offline,
	
		[Parameter(ParameterSetName="online")]
		[switch]
		$online,
	
		[Parameter(ParameterSetName="restrict")]
		[switch]
		$Restrict,
	
		[Parameter(ParameterSetName="restrict",HelpMessage="If a volume contains CIFS shares, users should be warned before restricting/offlining the volume.")]
        [Parameter(ParameterSetName="offline",HelpMessage="If a volume contains CIFS shares, users should be warned before restricting/offlining the volume.")]
		[int]
		$CifsDelay,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
    Process{
        switch ($PSCmdlet.ParameterSetName)
		{
            "online" 
            {
    			$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-online")
	       		$msg = "Online volume"
		    }
    		"offline" 
            {
    			$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-offline")
    			$msg = "Offline volume"
    			if ($CifsDelay) 
                {
                    $request.AddNewChild("cifs-delay",$CifsDelay)
                }
    		}
    		"Restrict" 
            {
    			$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-restrict")
    			$msg = "Restrict volume"
    			if ($CifsDelay) 
                {
                    $request.AddNewChild("cifs-delay",$CifsDelay)
                }
    		}
		}
        $request.AddNewChild("name",$Name)
        if ($pscmdlet.ShouldProcess($Name,$msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				Get-NaVol -volume $Name -server $server
			}
		}
	}
}
function Get-NaVolSize {
	<#
	.Synopsis
   		Given the name of a flexible volume, either return its current size or set the volume's size to the stated amount.
	.Description
   		Given the name of a flexible volume, either return its current size or set the volume's size to the stated amount.
	.Parameter Name
   		The name of the flexible volume for which we want to get it's size. 
	.Parameter Server
	    NaServer to query
	.Example
		# get the size settings for all volumes
   		PS > Get-naVol | Get-NaVolSize
   	.Outputs
    	NetApp.SDK.NaVolumeSize[]
    .Link
    	Get-NaVol
    	Set-NaVolSize
	#>
	[CmdletBinding(SupportsShouldProcess=$TRUE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param (
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the flexible volume for which we want to get autosize.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-size")
		$request.AddNewChild("volume",$name)
        Try {
		  $result = ([xml]$server.InvokeElem($request)).results
        }
        catch [NetApp.Manage.NaApiFailedException] {
            Write-Warning $_.Exception.GetBaseException().message
            $result = $null
            continue;
        }
		if ($?){
			$Size = switch -regex ($result."volume-size")
			{
				"(?<size>\d+)t" {[Int64]$matches.size * 1tb}
				"(?<size>\d+)g" {[Int64]$matches.size * 1gb}
				"(?<size>\d+)m" {[Int64]$matches.size * 1mb}
				"(?<size>\d+)k" {[Int64]$matches.size * 1kb}
				default 	 {$_}
			}
			return New-Object NetApp.SDK.NaVolumeSize -ArgumentList @(
				$name,
				$Size,
				(ConvertFrom-NaBool $results."is-fixed-size-flex-volume"),
				(ConvertFrom-NaBool $results."is-readonly-flex-volume"),
				(ConvertFrom-NaBool $results."is-replica-flex-volume")
			)
		}
	}
}
function Set-NaVolSize {
	<#
	.Synopsis
   		Given the name of a flexible volume, Set the size. 
	.Description
   		Given the name of a flexible volume, Set the size. 
	.Parameter Name
   		The name of the flexible volume for which we want to Set the size. 
	.Parameter Size
   		The Desired volume size in 'kilobytes'
	.Parameter Server
	    NaServer to query
	.Example
		Set-NaVolSize vol1 20gb
        
        Set vol1 to 20gb
	.Example
		Get-naVol |% { Set-NaVolSize -Name $_.volume -size ([math]::round(($_.SizeTotal * .2) + $_.SizeTotal)) + $_.SizeTotal))
        
        Grow all volumes by 20%
   	.Outputs
    	NetApp.SDK.NaVolumeSize[]
    .Link
    	Get-NaVol
    	Get-NaVolSize
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param (
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the parent flexible volume for the clone.")]
		[Alias("Volume")]
		[STRING]
		$Name,

		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,Position=0,HelpMessage="Desired volume size in 'kilobytes'")]
		[Int64]
		$Size,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{ 
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-size")
		$request.AddNewChild("volume",$Name)
		$request.AddNewChild("new-size",$Size)
		
        if ($pscmdlet.ShouldProcess($server.Server, "Resizing $name to $($Size)K")){
			try {
				$result = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
				$Size = switch -regex ($result."volume-size")
				{
					"(?<size>\d+)t" {[Int64]$matches.size * 1tb}
					"(?<size>\d+)g" {[Int64]$matches.size * 1gb}
					"(?<size>\d+)m" {[Int64]$matches.size * 1mb}
					"(?<size>\d+)k" {[Int64]$matches.size * 1kb}
					default 	 {$_}
				}
				return New-Object NetApp.SDK.NaVolumeSize -ArgumentList @(
					$Name,
					$Size,
					(ConvertFrom-NaBool $results."is-fixed-size-flex-volume"),
					(ConvertFrom-NaBool $results."is-readonly-flex-volume"),
					(ConvertFrom-NaBool $results."is-replica-flex-volume")
				)
			}
		}
	}
}
function Get-NaVolOptions {
	<#
	.Synopsis
   		Get the options that have been set for the specified volume.
	.Description
   		Get the options that have been set for the specified volume.
	.Parameter Name
   		Name of the existing volume for which we want option information. 
	.Parameter Server
	    NaServer to query
	.Example
		Get-NaVolOptions vol2
        
        # Get the options from vol2
   	.Outputs
    	PSObject[]
    .Link
    	Get-NaVol
    	Set-NaVolOptions
	#>
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]	
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Get the options that have been set for the specified volume.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
        [Parameter(Position=1,HelpMessage="Name of the option we want.")]
        [STRING]
        $OptionName,
    
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-options-list-info")
		$request.AddNewChild("volume",$Name)
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result.options."volume-option-info" | Select-Object @{
				Expression={$Name}
				Name='Volume'
			},
			@{
				Expression={$_.name}
				Name='OptionName'
			},
			@{
				Expression={$_.value}
				Name='Optionvalue'
			} | Where-Object {$_.OptionName -match $OptionName}
		}
	}
}
function Set-NaVolOptions {
	<#
	.Synopsis
    	Get the options that have been set for the specified volume.
	.Description
      	Set the option named -name to the value specified by -value in the specified volume.
      	The change remains effective even after the filer is rebooted. Some options have 
      	values that are numbers, and others have values that are 'on'(also expressible as 
      	'yes', 'true', or '1' ) or "off" (also expressible as 'no', 'false', or '0'). A 
      	mixture of uppercase and lowercase characters may be used for an option's value. 
      	
    	Note: The 'root' option is special in that it does not have an associated value. 
    	Also, note that some of these options can NOT be set for a flexible volume, as 
    	they relate only to aggregates (either free-standing ones or those embedded in 
    	traditional volumes).
	.Parameter Name
    	Name of the option to be set. Possible values:
	"convert_ucode" (value: "on" |"off")
   		Setting this option to "on" forces conversion of all directories to
		UNICODEformat when accessed from both NFS and CIFS. By default, it is set to
		"off",in which case access from CIFS causes conversion of pre-4.0 and 4.0-
		formatdirectories. Access from NFS causes conversion of 4.0 format directories.
	"snapshot_clone_dependency"(value: "on" | "off")
	   	 Setting this option "on" willunlock all initial and intermediate backing
	   	 snapshots for all inactive LUN clones. For active LUN clones, only the 
	   	 backing snapshot will be locked. If the optionis "off" the backing snapshot
	   	 will remain locked until all intermediate backingsnapshots are deleted.
	"create_reserved"
    	This option is no longer supported.
	"create_ucode" (value: "on" | "off")
    	Setting this option to "on" forces UNICODE format directories to be 
    	created by default, both from NFS and CIFS. The default value is "off",
    	in which case all directories are created in pre-4.0format and only 
    	converted to UNICODE format upon the first CIFS access.
	"extent"(value: "on" | "off")
    	Setting this option to "on" enables extents in the volume. 
    	This causes application writes to be written in the volume as a
		write of a larger group of related data blocks called an extent. Using extents
		may help workloads that perform many small random writes followed by large
		sequential reads. However, using extents may increase the amount of disk
		operations performed on the filer, so this option should only be used where
		applicable. The default value is "off", in which case extents are not used.
	"fractional_reserve"(value: < number >)
    	This option decreases the amount of
		space reserved for overwrites of reserved objects (LUNs, files) in a volume. The
		option is set to 100 by default and indicates that 100% of the required reserved
		space will actually be reserved so the objects are fully protected for
		overwrites. The value can vary from 0 to 100. Using a value of less than 100
		indicates what percentage of the required reserved space should actually be
		reserved. This returns the extra space to the available space for the volume,
		decreasing the total amount of space used. However, this does leave the protected
		objects in the volume vulnerable to out of space errors since less than 100% of
		the required reserved space is actually reserved. If reserved space becomes
		exhausted this will cause disruptions on the hosts using the objects. If the
		percentage is decreased below 100%, it is highly recommended that the
		administrator actively monitor the space usage on the volume and take corrective
		action if the reserved space nears exhaustion.
	"fs_size_fixed" (value: "on" | "off")
   		Setting this option to "on" causes the file system to remain the same
		size (and not grow) when a SnapMirror relationship is broken, or when a "vol/aggr
		add" is performed on it. This option is automatically set to be "on" when a
		volume becomes a SnapMirrored. It remains "on" after the "snapmirror break"
		command is issued for the volume. This option allows a volume to be SnapMirrored
		back to the source without needing grow the source volume. If the volume size is
		larger than the file system size, turning off this option forces the file system
		to grow to the size of the volume.
	"guarantee" (value: "none" | "file" |"volume")
   		Flexible volumes only. Setting this option controls the type of
		space reservation for the named flexible volume. There are three possible
		settings. The first, "none", provides no guarantee that there will be enough
		block sin the containing aggregate to meet the flexible volume's needs. The
		second, "file", guarantees there will be enough blocks in the containing
		aggregate to meet the needs of the specified files in the flexible volume. The
		third, "volume", is the default setting and guarantees there will be enough
		blocks available in the containing aggregate to meet the entire flexible volume's
		needs. An error will be returned if an attempt is made to set this option on a
		traditional volume.
	"ignore_inconsistent" (value: "on" | "off")
    	This option canonly be set in maintenance mode. If set to "on", then the root 
    	volume may be brought online when booting even if it is marked as inconsistent.
    	The user is cautioned that bringing it online prior to running WAFL_check or 
    	wafliron may resultin further file system inconsistency.
	"maxdirsize" (value: < number >)
		Set the maximum size (in KBytes) to which any directory can grow. The default
		setting of 10240 limits directory size to 10 MBytes and allows it to hold up to
		approximately 300,000 files. The number of files that the directory actually can
		hold varies depending on such things as the length of the names and whether it
		needs to use double-byte UNICODE characters. Most users should not need to change
		this option's setting. This option is useful for environments where system users
		may grow a directory to a size that starts impacting system performance. When a
		user tries to create a file in a directory that is at the limit, the system
		returns a ENOSPC error and fails the create.
	"minra" (value: "on" | "off")
		Setting this option to "on" causes the filer to perform minimal read-ahead on
		this volume. By default, this option is "off", causing the filer to perform very
		aggressive read-ahead on the volume.
	"no_atime_update" (value: "on" | "off")
		Setting this option to "on" prevents the update of inode access times when a file
		is read. This option is useful for volumes with extremely high read traffic,
		since it prevents writes to the inode file for the volume from contending with
		reads from other files. It should be used carefully. That is, use this option
		when you know in advance that the correct access time for inodes will not be
		needed for files on that volume.
	"no_i2p" (value: "on" | "off")
	    Setting this optionto "on" disables inode to parent pathname translations on the 
	    volume. The defaultsetting is off.
	"nosnap" (value: "on" | "off")
    	Setting this option to "on" disables automatic snapshots on the volume.
	"nosnapdir" (value: "on" | "off")
   		Setting this option to "on" disables the visible .snapshot directory
		that is normally present at system internal mount points. It also turns off
		access to all other .snapshot directories in the volume.
	"nvfail" (value : "on" |"off")
    	If this option is on, the filer performs additional work at boot
		time if it finds that there has been any potential data loss due to an NVRAM
		failure. In such situations, it causes the invalidation of all NFS file handles
		on all volumes affected by the problem so that client-side users are forced to
		remount the affected file system (and thus not continue to use potentially
		incorrect data). It is also possible to specify a set of files per volume that
		are to be renamed out of the way in these cases. The filer sends error messages
		to the console whenever such problems are found.
	"raid_cv" (value: "on" | "off")
   		Traditional volumes only. Setting the option to "off" disables block
		checksum protection on the volume. The default is "on". The user is cautioned
		that turning off the option exposes the filesystem to inconsistency that could be
		caused by a misbehaving hardware component in the system.
	"raid_zoned" (value: "on"| "off")
    	Traditional volumes only. Setting the option to "off" disables
		zoned checksum protection on the volume. The default is "on". The user is
		cautioned that turning off the option exposes the filesystem to inconsistency
		that could be caused by a misbehaving hardware component in the system.
	"raidsize"(value: < number >)
    	Traditional volumes only. The maximum size of
		a RAID group within the traditional volume. Changing this option doesn't cause
		existing RAID groups to grow or shrink. Rather, it only affects whether more
		disks will be added to the last existing RAID group in the future, and how large
		new RAID groups will be.
	"raidtype" (value: "raid4" | "raid_dp")
	    Traditional volumesonly. The type of RAID group used for this traditional volume. The
		"raid4" setting provides one parity disk per RAID group, while "raid_dp" provides
		two. Changing this option immediately changes the RAID group type for all RAID
		groups in the traditional volume. When upgrading RAID groups from "raid4" to
		"raid_dp", each RAID group begins reconstruction onto a spare disk allocated for
		the second "dparity" parity disk.
	"resyncsnaptime" (value: < number >)
		Traditional volumes only. Sets the RAID mirror resynchronization snapshot
		frequency to be the given number of minutes. The default value is '60' (minutes).
	"root"(value: < none >)
    	The specified volume is to become the root volume
		for the filer on the next reboot. This option can be used on only one volume at
		any given time. The existing root volume will become a non-root volume after the
		reboot. Until the system is rebooted, the current root volume will continue to
		show 'root' as one of its options, and the new root volume will show 'diskroot'
		as an option. In general, the volume that has the 'diskroot' option value is the
		one that becomes the root volume following the next reboot. The only way to
		remove the root status of a volume is to set it on another one.
	"schedsnapname" (value:"create_time" | "ordinal")
     	Setting the option to "ordinal" causes
		scheduled snapshots to be named in the hourly.n name format. Setting the value to
		"create_time" causes snapshots to use a hourly.yyyy-mm-dd_hhmm name format
		instead. The default is "ordinal".
	"snapmirrored" (value : "off")
    	If SnapMirroris enabled, the filer automatically sets this option to "on". Set this
		option to "off" if SnapMirror should no longer be used to update the mirror.
		After setting this option to "off", the mirror becomes a regular writable volume.
		This option can only be set to "off" with this interface. Only the filer can
		change this option's value from "off" to "on".
	"try_first" (value : "volume_grow"| "snap_delete")
    	If the flexible volume is configured to
		automatically reclaim space if the volume is running out of space, then setting
		this option to "volume_grow" will cause the volume to increase in size before
		deleting snapshots. If the option was set to "snap_delete", snapshots will be
		deleted before the volume size is increased.
	"svo_enable" (value: "on" | "off")
  		Setting this option to "on" enables SnapValidator functionality on this
		volume. This option only applies to non-root volumes.
	"svo_allow_rman" (value: "on"| "off")
    	Setting this option to "on" enables SnapValidator functionality
		on this volume to allow this volume to contain Oracle RMAN backup data. This
		option only applies to non-root volumes.
	"svo_checksum" (value: "on" | "off")
		Setting this option to "on" enables SnapValidator checksumming of all writes to
		this volume. This option only applies to non-root volumes.
	"svo_reject_errors" (value:"on" | "off")
    	Setting this option to "on" enables SnapValidator
		functionality to reject any write to the volume which fails the SnapValidator
		checks. This option only applies to non-root volumes.
	"thorough_scrub" (value: "on"| "off")
    	Traditional volumes only. Setting the option to "on" enables
		thorough scrub on a block checksum volume. That means that a scrub will
		initialize any zeroed checksum entries that it finds. If there are any checksum
		entries to be initialized, scrub will run slower than normal.
	"compression" (value:"on" | "off")
    	Flexible volumes only. Setting the option to "on"
		enables compression on the volume. All new writes to the volume will write
		compressed data on disk. It does not compress the existing data in the volume.
		Setting the option to "off" disables compression on volume, it does not
		decompress existing compressed data on volume.
	.Parameter OptionValue
       	The value to set the named option (except for option 'root').
	.Parameter Volume
       	Name of the volume for which we want to set an option. 
	.Parameter Server
      	NaServer to query
	.Example
	    # Set the compression option on vol1
      	PS > Set-NaVolOptions -OptionName compression -OptionValue on -volume vol1
	.Example
	  	# Copy all the option settings from vol1 to vol2
      	PS > Get-NaVolOptions vol1 | Set-NaVolOptions -volume vol2
    .Outputs
    	PSObject[]
    .Link
    	Get-NaVol
    	Get-NaVolOptions
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]	
	param(
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the option to be set.")]
		[STRING]
		$OptionName,
	
		[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The value to set the named option. (except for option 'root', which has no associated value).")]
		[STRING]
		$OptionValue,
	
		[Parameter(Position=2,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume for which we want to set an option.")]
		[STRING]
		$Volume,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-set-option")
		$request.AddNewChild("volume",$Volume)
		$request.AddNewChild("option-name",$OptionName)
		$request.AddNewChild("option-value",$OptionValue)
        if ($pscmdlet.ShouldProcess($Volume, "Setting $OptionName to $OptionValue")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
            	return Get-NaVolOptions -Name $Volume -OptionName $OptionName -server $server
			}
		}
	}

}
function Get-NaVolAutoSize{
	<#
	.Synopsis
   		Given the name of a flexible volume, get the autosize settings. 
	.Description
   		Given the name of a flexible volume, get the autosize settings. 
	.Parameter Name
   		The name of the flexible volume for which we want to get autosize. 
	.Parameter Server
	    NaServer to query
	.Example
		# get the autosize settings for all volumes
   		PS > Get-naVol | Get-NaVolAutoSize
   	.Outputs
    	NetApp.SDK.NaVolumeAutoSize[]
    .Link
    	Get-NaVol
    	Set-NaVolAutoSize
	#>
	[CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want to get autosize.")]
        [Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-autosize-get")
		$request.AddNewChild("volume",$name)
        Try{
		  $result = ([xml]$server.InvokeElem($request)).results
        }
        catch [NetApp.Manage.NaApiFailedException]{
            Write-Warning $_.Exception.GetBaseException().message
            $result = $null
            continue;
        }
		if ($?) {
			return New-Object NetApp.SDK.NaVolumeAutoSize -ArgumentList @(
				$Name,
				(ConvertFrom-NaBool $result."is-enabled"),
				$result."increment-size",
				$result."maximum-size"
			)
		}
	}
}
function Set-NaVolAutoSize {
	<#
	.Synopsis
   		Given the name of a flexible volume, set the autosize settings.  
	.Description
   		Given the name of a flexible volume, set the autosize settings.  
	.Parameter Name
   		The name of the flexible volume for which we want to Set autosize. 
	.Parameter Increment
   		Specify the flexible volume's increment size in kilobytes.
	.Parameter MaxSize
   		Specify the flexible volume's maximum allowed size in kilobytes.
	.Parameter Enable
   		set the vol autosize feature to enabled.
	.Parameter Disable
   		set the vol autosize feature to disabled.
	.Parameter Server
   		NaServer to query
	.Example
 		Enable vol5 to autosize with an incremental growth of 500mb and a max size of 10gb
   		Set-NaVolAutoSize -Name vol5 -Increment 500mb -MaxSize 10gb -enable
	.Example
		# Disable autosize on all volumes.
   		get-navol | Set-NaVolAutoSize -Disable
   	.Outputs
    	NetApp.SDK.NaVolumeAutoSize[]
    .Link
    	Get-NaVol
    	Get-NaVolAutoSize
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(ParameterSetName="size",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the flexible volume for which we want to get autosize.")]
        [Parameter(ParameterSetName="enable",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the flexible volume for which we want to get autosize.")]
        [Parameter(ParameterSetName="disable",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the flexible volume for which we want to get autosize.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(ParameterSetName="size",HelpMessage="Specify the flexible volume's increment size in kilobytes.")]
		[int64]
		$increment,
	
		[Parameter(ParameterSetName="size",HelpMessage="Specify the flexible volume's maximum allowed size in kilobytes.")]
		[int64]
		$maxSize,
	
		[Parameter(ParameterSetName="enable")]
		[switch]
		$disable,
	
		[Parameter(ParameterSetName="disable")]
		[switch]
		$enable,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-autosize-set")
		$request.AddNewChild("volume",$Name)
        switch ($PSCmdlet.ParameterSetName) {
		    "disable"
            { 
    		    $request.AddNewChild("is-enabled",$FALSE)
    			$msg = "Disable vol autosize "
    		}
            "enable"
            {
    			$request.AddNewChild("is-enabled",$TRUE)
    			$msg = "enable vol autosize "
    		}
            "size"
            {
        		if ($increment){
        			$request.AddNewChild("increment-size",$increment)
        			$msg += "set vol autosize increment:$($increment)K"
        		}
        		if ($maxSize){
        			$request.AddNewChild("maximum-size",$maxSize)
        			$msg += " set maxfile size:$($maxsize)K"
        		}
            }
        }		
        if ($pscmdlet.ShouldProcess($Name, $msg)) 
        {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaVolAutoSize -volume $name -Server $server
			}
		}
	}
}
function Get-NaVolCharmap {
	<#
	.Synopsis
   		Return charmap information for a specified volume. 
	.Description
   		Return charmap information for a specified volume. 
	.Parameter Name
   		The name of the volume on which to list the charmap information. 
	.Parameter Server
	    NaServer to query
	.Example
		# get the Charmap association for vol1
   		PS > Get-NaVolCharmap -Name vol1
   	.Outputs
    	PSObject[]
    .Link
    	Get-NaVol
    	Set-NaVolCharmap
	#>
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume on which to list the charmap information. ")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-charmap-get")
		$request.AddNewChild("volume",$Name)
		return $server.InvokeElem($request).GetchildContent("charmap") | 
        Select-Object @{
			Expression={$Name}
			Name='Volume'
		},
        @{
			Expression={$_.charmap}
			Name='Charmap'
		}
	}
}
function Set-NaVolCharmap {
	<#
	.Synopsis
   		Associate a charmap description with a specified volume.
	.Description
   		Associate a charmap description with a specified volume.
	.Parameter Name
  		Name of the volume with which the charmap is to be associated. 
	.Parameter Charmap
   		Description of the character mapping to be done for this volume. This mapping is to allow CIFS
		clients to use NFS file names that would otherwise result in invalid CIFS names. The values are
 		comma-separated pairs of hex character mappings. The A-F hex values can be in upper or lower case,
  		and the values do not have to be padded. Example: "5c:f2e1,3c:b6,3e:ae,7C:394". If a value is not 
 		passed, any existing charmap will be removed.
	.Parameter Server
	    NaServer to query
	.Example
		# Set the charmap for vol1
   		Set-NaVolCharmap -Name vol1 -charmap "5c:f2e1,3c:b6,3e:ae,7C:394"
	.Example
		# remove all charmaps from vol1
   		Set-NaVolCharmap -Volume vol1
   	.Outputs
    	PSObject[]
    .Link
    	Get-NaVol
    	Get-NaVolCharmap
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume with which the charmap is to be associated.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="Description of the character mapping to be done for this volume.")]
		[string]
		$Charmap,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-charmap-set")
		$request.AddNewChild("volume",$Name)
		if ($Charmap){ 
			$request.AddNewChild("charmap",$Charmap)
			$msg = "Setting character mapping to $Charmap"
		} 
        else{
			$msg = "Removing character mapping"
		}
		if ($pscmdlet.ShouldProcess($Name, $msg)){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaVolCharmap -Name $Name -Server $server
			}
		}
	}
}

function Get-NaFlexCloneSplit {
	<#
	.Synopsis
   		Display the progress in separating clones from their underlying parent volumes and snapshots.
	.Description
   		Display the progress in separating clones from their underlying parent volumes and snapshots. If
		a clone name is specified, then the split status for that clone is provided. if no clone name is
		provided, then status is provided for all clones currently being split. This command fails if 
		applied to a traditional volume, and EONTAPI_EVOLNOTFLEX is thrown. Cloning is a capability that
		applies exclusively to flexible volumes. This command fails if the volume specified is not a clone,
		and EVOLNOTCLONE is thrown. This command fails if the volume specified is not being split, and 
		EVOLOPNOTUNDERWAY is thrown. 
	.Parameter Name
	  	The name of the clone being split off from its parent volume and snapshot for which we want status. 
	.Parameter Server
	    	NaServer to query
	.Example
		# Get the status of all clone split operations
	   	PS > Get-NaFlexCloneSpit 
	.Example
		# Get the status of vol2_clone clone split
   		Get-NaFlexCloneSpit -Name vol2_clone
   	.Outputs
    	NetApp.SDK.NaVolumeCloneSplitDetail[]
    .Link
    	Get-NaVol
    	Measure-NaFlexCloneSplit
    	New-NaFlexClone
    	Get-NaFlexClone
    	Split-NaFlexClone
    	Stop-NaFlexClone
	#>
	[CmdletBinding(SupportsShouldProcess=$False,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the clone being split off from its parent volume and snapshot for which we want status.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process 
    {
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-clone-split-status")
		if ($name){
            $request.AddNewChild("volume",$Name)
        }
        Try{
		  $result = ([xml]$server.InvokeElem($request)).results
        }
        catch [NetApp.Manage.NaApiFailedException]{
            Write-Warning $_.Exception.GetBaseException().message
            $result = $null
            continue;
        }
		if ($?) {
			$result."clone-split-details"."clone-split-detail-info" | % {
				return New-Object NetApp.SDK.NaVolumeCloneSplitDetail -ArgumentList @(
					$_."name",
					$_."blocks-scanned",
					$_."blocks-updated",
					$_."inode-percentage-complete",
					$_."inodes-processed",
					$_."inodes-total"
				)
			} | ?{$_.name -ne ''}
		}
	}
}
Function Measure-NaFlexCloneSplit {
	<#
	.Synopsis
   		Display an estimate of additional storage required in the underlying aggregate to perform a volume 
 		clone split operation.
	.Description
   		Display an estimate of additional storage required in the underlying aggregate to perform a volume 
 		clone split operation. This command fails if applied to a traditional volume. Cloning is a new 
		capability that applies exclusively to flexible volumes. 
	.Parameter Name
	  	The name of the clone whose split usage is being estimated. 
	.Parameter Server
	    NaServer to query
	.Example
		# Get the number of blocks needed to split Vol2_clone from Vol2
   		PS > Measure-NaFlexCloneSplit -Name Vol2_clone
   	.Outputs
    	PSObject[]
    .Link
    	Get-NaVol
    	Get-NaFlexCloneSplit
    	New-NaFlexClone
    	Get-NaFlexClone
    	Split-NaFlexClone
    	Stop-NaFlexClone
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the clone whose split usage is being estimated.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-clone-split-estimate")
		$request.AddNewChild("volume",$Name)
		try {
			$result = ([xml]$server.InvokeElem($request)).results 
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."clone-split-estimate" | % {
				$obj = "" | select Volume, Blocks
				$obj.Volume = $Name
				# < 1.7
				if ([int]$_."clone-split-estimate-info"."estimate-blocks") 
				{
					$obj.Blocks = $_."clone-split-estimate-info"."estimate-blocks"
				}
				# >1.7
				if ([int]$_."estimate-blocks") 
				{
					$obj.Blocks = $_."estimate-blocks"
				}
			}
			return $obj
		}
	}
}
function New-NaFlexClone {
	<#
	.Synopsis
   		Create a flexible volume that is a clone of a "backing" or "parent" flexible volume.
	.Description
		Create a flexible volume that is a clone of a "backing" or "parent"
		flexible volume. A clone is a Volume that is a writable snapshot of another
		volume. Initially, the clone and its parent share the same storage; more storage
		space is consumed only as one volume or the other changes. if a specific
		snapshot name within the parent volume is provided, it is chosen as the parent
		snapshot. Otherwise, the filer will create a new, distinctively- named snapshot
		in the parent volume for that purpose.  The parent snapshot is locked in the
		parent volume, preventing its deletion until the clone is either destroyed or
		split from the parent using the Split-NaFlexClone cmdlet. This Command fails if
		the chosen parent volume is currently involved in a split operation. This
		command also fails if the chosen parent volume is a traditional volume. Cloning
		is a new capability that applies exclusively to flexible volumes.
	.Parameter Name
	  	Desired name of the clone.
	.Parameter Volume
	  	Name of the parent flexible volume for the clone. 
	.Parameter Snapshot
		Name of the snapshot within 'parent-volume' that is to serve as the
		parent snapshot for the clone. If not provided, the filer will create a new
		snapshot named 'clone_parent_' (using a freshy-generated UUID) in
		'parent-volume' for this purpose.
	.Parameter SpaceReserve
		Specifies the type of volume guarantee for the clone. Possible values: none, 
		file, volume. If this argument is not provided, the default volume guarantee 
		type is volume. 
	.Parameter ForceWORM
	  	If specified force the creation of clone on a worm volume. Otherwise clone creation
	  	on any worm volume will fail, because clones of worm volumes are not deletable until
	  	all the inherited worm files on newly created clone have expired.
	.Parameter Server
	    NaServer to query
	.Example
		# Create a new FlexClone named clone1 from vol1
	   	PS > New-NaFlexClone -name clone1 -volume vol1
	.Example
		# Create a new FlexClone named clone1 from a snapshot on vol1 named clone_source
	    New-NaFlexClone -name clone1 -volume vol1 -Snapshot clone_source
	.Outputs
    	NetApp.SDK.NaVol[]
    .Link
    	Get-NaVol
    	Get-NaFlexClone
    	Split-NaFlexClone
    	Stop-NaFlexClone
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]	
	param (
		[Parameter(Mandatory=$TRUE,Position=0,HelpMessage="Desired name of the clone.")]
		[STRING]
		$Name,
	
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,Position=1,HelpMessage="Name of the parent flexible volume for the clone."
		)]
		[STRING]
		$Volume,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the snapshot within 'parent-volume'."
		)]
		[string]
		$Snapshot,
	
		[Parameter(HelpMessage="Specifies the type of volume guarantee for the clone.")]
		[ValidateSet("none", "file", "volume")]
		[string]
		$SpaceReserve,
	
		[Parameter()]
		[switch]
		$ForceWORM,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process { 
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-clone-create")
		$request.AddNewChild("volume",$name)
		$request.AddNewChild("parent-volume",$Volume)
		if ($Snapshot){
			$request.AddNewChild("parent-snapshot", $Snapshot)
		}
		if ($SpaceReserve){
			$request.AddNewChild("space-reserve",$SpaceReserve)
		}
		if ($ForceWORM){
			$request.AddNewChild("force-worm-clone",$TRUE)
		}
		if ($pscmdlet.ShouldProcess($server.Server, "Create new FlexClone $name")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaVol -Volume $Name -Server $server 
			}
		}
	}
}
Function Split-NaFlexClone {
	<#
	.Synopsis
   		Begin the process by which the given clone is split off from its underlying parent
   		volume and snapshot.
	.Description
		Begin the process by which the given clone is split off from its
		underlying parent volume and snapshot. New storage is allocated for the clone
		that is distinct from its parent. This process may take some time and proceeds
		in the background. Use the Get-NaFlexCloneSpit cmdlet to view the operation's
		progress. Both clone and parent volumes remain available during the process of
		splitting them apart. Upon completion, the snapshot on which the clone was based
		will be unlocked in the parent volume. Any snapshots in the clone are removed at
		the end of processing. Use the Stop-NaFlexCloneSplit cmdlet to stop this
		process. This command fails if applied to a traditional volume. Cloning is a new
		capability that applies exclusively to flexible volumes.
	.Parameter Name
  		Name of the clone that we want split off from its parent volume and snapshot.
	.Parameter Server
    	NaServer to query
	.Example
		# split vol2 from vol1
   		PS > Split-NaFlexClone vol2
   	.Outputs
    	NetApp.SDK.NaVol
    .Link
    	Get-NaVol
    	Get-NaFlexClone
    	Stop-NaFlexClone
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the clone that we want split off from its parent volume and snapshot.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-clone-split-start")
		$request.AddNewChild("volume",$Name)	
        if ($pscmdlet.ShouldProcess($name, "starting vol clone split")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaFlexCloneSplit -volume $Name -server $server
			}
		}
	}
}
Function Stop-NaFlexCloneSplit {
	<#
	.Synopsis
   		Display the progress in separating clones from their underlying parent volumes and snapshots.
	.Description
   		Stop the process of splitting off a clone from its parent volume and snapshot. All of the blocks 
		that were formerly shared between the given clone and its parent volume that have already been 
		split off will remain that way. This command fails if applied to a traditional volume. Cloning 
 		is a new capability that applies exclusively to flexible volumes. 
	.Parameter Name
	  	The name of the clone for which we want to stop the process of being split off from its parent
	  	volume and snapshot.
	.Parameter Server
	    NaServer to query
	.Example
		# Stop the process of splitting off vol2 from its parent volume vol1
   		PS > Stop-NaFlexCloneSpit -Name vol2
   	.Link
    	Get-NaVol
    	Get-NaFlexClone
    	Split-NaFlexClone
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the clone for which we want to stop the process of being split off from its parent volume and snapshot")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("volume-clone-split-stop")
		$request.AddNewChild("volume",$Name)
		if ($pscmdlet.ShouldProcess($Name, "stop clone split operation")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}

		}

	}
}
function Start-NaVolDecompress {
	<#
	.Synopsis
   		Start decompression of data in a volume.
	.Description
   		Start decompression of data in a volume. The volume should should have compressed
   		data and it should not have compression option enabled. 
	.Parameter Name
	  	Name of the volume. Ex: flex1, vol0 etc. 
	.Parameter Server
	    NaServer to query
	.Example
		# Decompress all the data on vol1
   		PS > Get-NaVol vol1 | Start-NaVolDecompress
    .Link
    	Get-NaVol
    	Stop-NaVolDecompress
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-decompress-start")
		$request.AddNewChild("volume",$Name)
		if ($pscmdlet.ShouldProcess($Name, "starting vol decompress")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
function Stop-NaVolDecompress {
	<#
	.Synopsis
   		Abort in-progress decompression scan of data in volume. 
	.Description
   		Abort in-progress decompression scan of data in volume. 
	.Parameter Name
	  	Name of the volume. Ex: flex1, vol0 etc. 
	.Parameter Server
	    NaServer to query
	.Example
		# Abort an in progress decompress scan on vol1
   		PS > Stop-NaVolDecompress vol1
   	.Link
    	Get-NaVol
    	Start-NaVolDecompress
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="Low",DefaultParameterSetName="")]	
	param ( 
		[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the clone for which we want to stop the process of being split off from its parent volume and snapshot")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement  -ArgumentList @("volume-decompress-abort")
		$request.AddNewChild("volume",$name)
		if ($pscmdlet.ShouldProcess($Name, "stopping vol decompress")){
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		}
	}
}
